﻿using SmartSapce.ServiceLocation;
using SmartSpace.Core;
using SmartSpace.Packaging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PublishTool
{
    public class Program
    {
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {

                string filePath = args[0];

                if (filePath.ToLower().EndsWith(".sstp"))
                {
                    PublishTemplate(filePath);
                }
                else if (filePath.ToLower().EndsWith(".ssmp"))
                {
                    PublishModule(filePath);
                }
                else
                {
                    Console.WriteLine("unknown file type!");
                }
            }
            else
            {
                Console.WriteLine("no file parameter!");
            }
            Console.WriteLine("press any key to exit...");
            Console.ReadKey();
        }

        static void PublishModule(string filePath)
        {
            try
            {
                Console.WriteLine("stoping iis...");
                ProcessStartInfo psi = new ProcessStartInfo("iisreset", "/stop");
                psi.RedirectStandardOutput = true;
                psi.RedirectStandardError = true;
                psi.UseShellExecute = false;
                psi.CreateNoWindow = true;
                Process pro = new Process();
                pro.StartInfo = psi;
                pro.Start();
                pro.WaitForExit(120000);
                Console.WriteLine("stop iis success!");
            }
            catch(Exception ex)
            {
                Console.WriteLine("stop iis failure!");
                Console.WriteLine(ex.Message);
            }

            string outDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("./{0}/", Guid.NewGuid().ToString("D")));
            Stream stream = new FileStream(filePath, FileMode.Open);
            PackageUtil.DecompressFile(stream, outDir);

            DirectoryInfo di = new DirectoryInfo(outDir);
            string xFile = di.GetFiles("*.xmml")[0].FullName;

            XModule module = PackageUtil.ParseXMML(xFile);

            // 移动文件
            foreach (XFile file in module.Files)
            {
                string destFile = Path.Combine(PublishUtility.GetSiteFolder(), file.Publish);
                string sourceFile = Path.Combine(outDir, file.Path);

                FileInfo fi = new FileInfo(destFile);
                if (!fi.Directory.Exists)
                {
                    Directory.CreateDirectory(fi.Directory.FullName);
                }

                if (File.Exists(destFile))
                {
                    File.Delete(destFile);
                }
                File.Move(sourceFile, destFile);
                Console.WriteLine(string.Format("copy {0}", sourceFile));
            }

            Directory.Delete(outDir, true);
            Console.WriteLine("delete temp directory");

            Console.WriteLine("update module info");
            if (SaveModule(ConvertModule(module)))
            {
                Console.WriteLine("publish module success!");
                try
                {
                    Console.WriteLine("starting iis...");
                    ProcessStartInfo psi = new ProcessStartInfo("iisreset", "/start");
                    psi.RedirectStandardOutput = true;
                    psi.RedirectStandardError = true;
                    psi.UseShellExecute = false;
                    psi.CreateNoWindow = true;
                    Process pro = new Process();
                    pro.StartInfo = psi;
                    pro.Start();
                    pro.WaitForExit(120000);
                    //Process.Start(psi);
                    Console.WriteLine("tart iis success!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("start iis failure!");
                    Console.WriteLine(ex.Message);
                }
            }
            else
            {
                Console.WriteLine("publish module failure!");
            }
        }

        static Module ConvertModule(XModule xModule)
        {
            Module module = new Module();
            module.Id = xModule.Id;
            module.Name = xModule.Name;
            module.Caption = xModule.Caption;
            module.Package = xModule.Package;
            module.Settings = xModule.Settings;
            module.Type = xModule.Type;
            module.Version = xModule.Version;
            module.Views = new List<ModuleView>();
            foreach (var xView in xModule.Views)
            {
                ModuleView view = new ModuleView();
                view.Id = xView.Id;
                view.Caption = xView.Caption;
                view.Name = xView.Name;
                view.ModuleId = module.Id;
                module.Views.Add(view);
            }
            return module;
        }

        public static bool SaveModule(Module module)
        {
            try
            {
                using (PTDbContext context = new PTDbContext(PublishUtility.GetConnectionString(PublishUtility.GetSiteFolder())))
                {
                    if (context.Set<Module>()
                        .Where(p => p.Id == module.Id)
                        .Select(p => new { p.Id })
                        .FirstOrDefault() == null)
                    {
                        context.Set<Module>().Add(module);
                    }
                    else
                    {
                        context.Entry(module).State = System.Data.Entity.EntityState.Modified;

                        List<ModuleView> existViews = context.Set<ModuleView>().Where(p => p.ModuleId == module.Id).ToList();
                        foreach (var existView in existViews)
                        {
                            bool isExist = false;
                            foreach (var view in module.Views)
                            {
                                if (existView.Id == view.Id)
                                {
                                    existView.Caption = view.Caption;
                                    existView.Name = view.Name;
                                    isExist = true;
                                    break;
                                }
                            }

                            if (!isExist)
                            {
                                context.Entry(existView).State = System.Data.Entity.EntityState.Deleted;
                            }
                            else
                            {
                                context.Entry(existView).State = System.Data.Entity.EntityState.Modified;
                            }
                        }

                        foreach (var view in module.Views)
                        {
                            bool isExist = false;
                            foreach (var existView in existViews)
                            {
                                if (existView.Id == view.Id)
                                {
                                    isExist = true;
                                    break;
                                }
                            }

                            if (!isExist)
                            {
                                context.Set<ModuleView>().Add(view);
                            }
                        }
                    }

                    context.SaveChanges();
                    return true;
                }
            }
            catch
            {
                return false;
            }
        }

        #region template
        static void PublishTemplate(string filePath)
        {
            try
            {
                Console.WriteLine("stoping iis...");
                ProcessStartInfo psi = new ProcessStartInfo("iisreset", "/stop");
                psi.RedirectStandardOutput = true;
                psi.RedirectStandardError = true;
                psi.UseShellExecute = false;
                psi.CreateNoWindow = true;
                Process pro = new Process();
                pro.StartInfo = psi;
                pro.Start();
                pro.WaitForExit(120000);
                Console.WriteLine("stop iis success!");
            }
            catch (Exception ex)
            {
                Console.WriteLine("stop iis failure!");
                Console.WriteLine(ex.Message);
            }

            string outDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("./{0}/", Guid.NewGuid().ToString("D")));
            Stream stream = new FileStream(filePath, FileMode.Open);
            PackageUtil.DecompressFile(stream, outDir);

            DirectoryInfo di = new DirectoryInfo(outDir);
            string xFile = di.GetFiles("*.xtml")[0].FullName;

            XTemplate template = PackageUtil.ParseXTML(xFile);

            // 移动文件
            foreach (XFile file in template.Files)
            {
                string destFile = Path.Combine(PublishUtility.GetSiteFolder(), file.Publish);
                string sourceFile = Path.Combine(outDir, file.Path);

                FileInfo fi = new FileInfo(destFile);
                if (!fi.Directory.Exists)
                {
                    Directory.CreateDirectory(fi.Directory.FullName);
                }

                if (File.Exists(destFile))
                {
                    File.Delete(destFile);
                }
                File.Move(sourceFile, destFile);
                Console.WriteLine(string.Format("copy {0}", sourceFile));
            }

            Directory.Delete(outDir, true);
            Console.WriteLine("delete temp directory");

            Console.WriteLine("update template info");
            if (SaveTemplate(ConvertTemplate(template)))
            {
                Console.WriteLine("publish module success!");
                try
                {
                    Console.WriteLine("starting iis...");
                    ProcessStartInfo psi = new ProcessStartInfo("iisreset", "/start");
                    psi.RedirectStandardOutput = true;
                    psi.RedirectStandardError = true;
                    psi.UseShellExecute = false;
                    psi.CreateNoWindow = true;
                    Process pro = new Process();
                    pro.StartInfo = psi;
                    pro.Start();
                    pro.WaitForExit(120000);
                    //Process.Start(psi);
                    Console.WriteLine("tart iis success!");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("start iis failure!");
                    Console.WriteLine(ex.Message);
                }
            }
            else
            {
                Console.WriteLine("publish module failure!");
            }
        }

        static Theme ConvertTemplate(XTemplate xTemplate)
        {
            Theme theme = new Theme();
            theme.Id = xTemplate.Id;
            theme.Caption = xTemplate.Caption;
            theme.Name = xTemplate.Name;
            theme.Package = xTemplate.Package;
            theme.PreviewImageUrl = xTemplate.PreviewImageUrl;
            theme.Type = xTemplate.Type;
            theme.Version = xTemplate.Version;
            return theme;
        }

        public static bool SaveTemplate(Theme theme)
        {
            try
            {
                using (PTDbContext context = new PTDbContext(PublishUtility.GetConnectionString(PublishUtility.GetSiteFolder())))
                {
                    if (context.Set<Theme>()
                        .Where(p => p.Id == theme.Id)
                        .Select(p => new { p.Id })
                        .FirstOrDefault() == null)
                    {
                        context.Set<Theme>().Add(theme);
                    }
                    else
                    {
                        context.Entry(theme).State = System.Data.Entity.EntityState.Modified;
                    }

                    if (context.SaveChanges() > 0)
                    {
                        return true;
                    }
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }
        #endregion
    }
}
